﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Xml;

namespace ProcessMonitor
{
    /// <summary>
    /// 进程添加修改相关逻辑
    /// </summary>
    public class ProLogic
    {
        private string xmlpath = AppDomain.CurrentDomain.BaseDirectory + "ProcessInfo.xml";

        private XmlDocument xmldoc = new XmlDocument();

        public static ProLogic Instance = new ProLogic();

        #region 支付成功委托
        /// <summary>
        /// 委托处理更新成功事件
        /// </summary>
        public delegate void DelegateUpdateResult(int proidx);
        /// <summary>
        /// 更新事件处理
        /// </summary>
        public event DelegateUpdateResult EventUpdateResultAnalysis;
        #endregion

        /// <summary>
        /// 启动的时候加载xml配置信息
        /// </summary>
        public void LoadXmlConfig()
        {
            if (File.Exists(xmlpath))
            {
                xmldoc = new XmlDocument();
                xmldoc.Load(xmlpath);

                ProcessData.processlist.Clear();

                int idx = 0;
                foreach (XmlNode item in xmldoc.SelectNodes("ProcessInfos/ProcessInfo"))
                {
                    ProcessData.processlist.Add(new ProcessInfo()
                    {
                        IndexNum = idx++,
                        kid = item.Attributes["ID"].Value.ToString(),
                        Name = item.Attributes["Name"].Value.ToString(),
                        Path = item.Attributes["Path"].Value.ToString(),
                        MaxCPU = item.Attributes["MaxCPU"].Value.ToString(),
                        MaxMemory = item.Attributes["MaxMemory"].Value.ToString(),
                        //PID = item.Attributes["PID"].Value.ToString(),
                        PID = "0",
                        Desc = item.Attributes["Desc"].Value.ToString(),
                        RestartTime = item.Attributes["RestartTime"].Value.ToString(),
                        IsRestart = Convert.ToBoolean(item.Attributes["IsRestart"].Value.ToString()),
                        StartTime = item.Attributes["StartTime"].Value.ToString(),
                        AutoReboot = item.Attributes?["AutoReboot"]?.Value?.ToString() ?? "",
                        RebootTimeSet = item.Attributes?["RebootTimeSet"]?.Value?.ToString() ?? "",
                        //IsDie = Convert.ToBoolean(item.Attributes["IsDie"].Value.ToString()),
                        IsDie = true,
                        Info = "-"
                    });
                }
            }
        }

        /// <summary>
        /// 启动了某个进程
        /// </summary>
        /// <param name="proIdx"></param>
        public void ReStartPro(int proidx, int pid, long memsize, bool isReboot, bool isstart)
        {
            ProcessData.processlist[proidx].PID = pid.ToString();
            ProcessData.processlist[proidx].IsDie = false;
            ProcessData.processlist[proidx].Info = "-";
            ProcessData.processlist[proidx].StartTime = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss");
            if (isReboot)
            {
                ProcessData.processlist[proidx].RestartTime = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss");
                ProLogic.Instance.SycnUpdateReStartTimeToXml(proidx, ProcessData.processlist[proidx].RestartTime);
            }
            EventUpdateResultAnalysis?.Invoke(proidx);
        }

        /// <summary>
        /// 修改了某个进程信息
        /// </summary>
        /// <param name="proIdx"></param>
        public void UpdatePro(int proidx)
        {
            EventUpdateResultAnalysis?.Invoke(proidx);
        }

        /// <summary>
        /// 启停监控 true启用 false禁用
        /// </summary>
        /// <param name="proidx"></param>
        /// <param name="proidx"></param>
        public void StartOrStopMonitor(int proidx, bool isstart)
        {
            ProcessData.processlist[proidx].IsRestart = isstart;
            SycnUpdateToXml(proidx, isstart);
            EventUpdateResultAnalysis?.Invoke(proidx);
        }

        /// <summary>
        /// 启停监控 true启用 false禁用
        /// </summary>
        /// <param name="proidx"></param>
        /// <param name="proidx"></param>
        public void DelPro(int proidx)
        {
            ProcessData.processlist.RemoveAt(proidx);
            EventUpdateResultAnalysis?.Invoke(proidx);
            SycnDelToXml(proidx);
        }

        /// <summary>
        /// 将修改同步到xml文件 true启用 false禁用
        /// </summary>
        /// <param name="proidx"></param>
        public void SycnUpdateToXml(int proidx, bool isstart)
        {
            var nodes = xmldoc.SelectNodes("//ProcessInfos//ProcessInfo");
            XmlElement node = (XmlElement)nodes[proidx];
            node.SetAttribute("IsRestart", isstart ? "True" : "False");
            xmldoc.Save(xmlpath);
        }


        /// <summary>
        /// 将修改同步到xml文件 true启用 false禁用
        /// </summary>
        /// <param name="proidx"></param>
        public void SycnUpdateReStartTimeToXml(int proidx, string restarttime)
        {
            var nodes = xmldoc.SelectNodes("//ProcessInfos//ProcessInfo");
            XmlElement node = (XmlElement)nodes[proidx];
            node.SetAttribute("RestartTime", restarttime);
            xmldoc.Save(xmlpath);
        }
        /// <summary>
        /// 将修改同步到xml文件 true启用 false禁用
        /// </summary>
        /// <param name="proidx"></param>
        private void SycnDelToXml(int proidx)
        {
            var nodes = xmldoc.SelectNodes("//ProcessInfos//ProcessInfo");
            XmlElement node = (XmlElement)nodes[proidx];
            node.ParentNode.RemoveChild(node);
            xmldoc.Save(xmlpath);
            foreach (var item in ProcessData.processlist.Where(p => p.IndexNum > proidx))
            {
                item.IndexNum = item.IndexNum - 1;
            }
        }
        /// <summary>
        /// 添加 编辑
        /// </summary>
        /// <param name="proname">进程名称 空格后面 可能有参数</param>
        /// <param name="propath"></param>
        /// <param name="desc"></param>
        /// <param name="proidx"></param>
        public void SyncAddEditToXml(string proname, string propath, string desc, int? proidx, string rebootset, string reboottime)
        {
            if (proidx.HasValue)
            {
                #region 编辑
                var nodes = xmldoc.SelectNodes("//ProcessInfos//ProcessInfo");
                XmlElement node = (XmlElement)nodes[proidx.Value];
                node.SetAttribute("Name", proname);
                node.SetAttribute("Path", propath);
                node.SetAttribute("Desc", desc);
                node.SetAttribute("AutoReboot", rebootset);
                node.SetAttribute("RebootTimeSet", reboottime);
                xmldoc.Save(xmlpath);
                #endregion

                ProcessData.processlist[proidx.Value].Name = proname;
                ProcessData.processlist[proidx.Value].Path = propath;
                ProcessData.processlist[proidx.Value].Desc = desc;
                ProcessData.processlist[proidx.Value].AutoReboot = rebootset;
                ProcessData.processlist[proidx.Value].RebootTimeSet = reboottime;

                EventUpdateResultAnalysis?.Invoke(proidx.Value);
            }
            else
            {
                #region 新增
                var id = DateTime.Now.ToString("yyyyMMddHHmmsssfffff");
                XmlElement xmlnew = xmldoc.CreateElement("ProcessInfo");
                xmlnew.SetAttribute("ID", id);
                xmlnew.SetAttribute("Name", proname);
                xmlnew.SetAttribute("Path", propath);
                xmlnew.SetAttribute("MaxCPU", "0");
                xmlnew.SetAttribute("MaxMemory", "0");
                xmlnew.SetAttribute("PID", "0");
                xmlnew.SetAttribute("Desc", desc);
                xmlnew.SetAttribute("RestartTime", "-");
                xmlnew.SetAttribute("IsRestart", "True");
                xmlnew.SetAttribute("StartTime", "-");
                xmlnew.SetAttribute("IsDie", "True");
                xmlnew.SetAttribute("AutoReboot", rebootset);
                xmlnew.SetAttribute("RebootTimeSet", reboottime);
                xmldoc.SelectSingleNode("ProcessInfos").AppendChild(xmlnew);
                xmldoc.Save(xmlpath);

                ProcessData.processlist.Add(new ProcessInfo()
                {
                    kid = id,
                    IndexNum = ProcessData.processlist.Count(),
                    Name = proname,
                    Path = propath,
                    Desc = desc,
                    MaxCPU = "-",
                    MaxMemory = "-",
                    PID = "0",
                    RestartTime = "-",
                    StartTime = "-",
                    IsDie = true,
                    IsRestart = true,
                    AutoReboot = rebootset,
                    RebootTimeSet = reboottime
                });

                EventUpdateResultAnalysis?.Invoke(99999);
                #endregion
            }

        }
    }
}
